package ai.people.netmon.warning.service.impl;

import ai.people.core.grpc.lib.es.BaseSearchServiceGrpc;
import ai.people.core.grpc.lib.es.SearchPageResponse;
import ai.people.core.grpc.lib.es.SearchRequest;
import ai.people.core.grpc.utils.ProtoJsonUtil;
import ai.people.core.security.support.RequestHolderUtil;
import ai.people.netmon.framework.domain.searchmsg.request.MessageRequest;
import ai.people.netmon.framework.domain.warning.entity.WarningLabelTree;
import ai.people.netmon.framework.domain.warning.entity.WarningSubject;
import ai.people.netmon.framework.domain.warning.entity.WarningSubjectAnalysis;
import ai.people.netmon.framework.domain.warning.request.subject.AddSubjectRequest;
import ai.people.netmon.framework.domain.warning.request.subject.SubjectWarningRequest;
import ai.people.netmon.framework.domain.warning.request.subject.UpdateSubjectRequest;
import ai.people.netmon.framework.domain.warning.vo.MessageContentVO;
import ai.people.netmon.framework.domain.warning.vo.SubjectAnalysisVO;
import ai.people.netmon.framework.domain.warning.vo.WarningSubjectVO;
import ai.people.netmon.framework.exception.enums.CommonEnum;
import ai.people.netmon.framework.exception.enums.TopicExceptionEnum;
import ai.people.netmon.framework.model.response.PageResponse;
import ai.people.netmon.framework.utils.AssertUtils;
import ai.people.netmon.utils.localdateUtil.DateTimeFormatterUtil;
import ai.people.netmon.warning.dict.DictGrpcClient;
import ai.people.netmon.warning.mapper.WarningSubjectMapper;
import ai.people.netmon.warning.service.WarningLabelTreeService;
import ai.people.netmon.warning.service.WarningSpeechTemplateService;
import ai.people.netmon.warning.service.WarningSubjectAnalysisService;
import ai.people.netmon.warning.service.WarningSubjectService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import lombok.RequiredArgsConstructor;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ligua
 * @description 针对表【warning_subject(预警主题表)】的数据库操作Service实现
 * @createDate 2022-07-28 17:50:38
 */
@Service
@RequiredArgsConstructor
public class WarningSubjectServiceImpl extends ServiceImpl<WarningSubjectMapper, WarningSubject>
        implements WarningSubjectService, WarningSpeechTemplateService<SubjectWarningRequest, MessageContentVO> {

    @Autowired
    private WarningSubjectAnalysisService warningSubjectAnalysisServiceImpl;

    private final WarningLabelTreeService warningLabelTreeServiceImpl;

    private static Map<String, String> emotionMaps = new HashMap<>();

    static {
        emotionMaps.put("0", "正面");
        emotionMaps.put("1", "中性");
        emotionMaps.put("2", "负面");
    }


    @GrpcClient(value = "NM-SERVICE-SEARCH-MSG")
    private BaseSearchServiceGrpc.BaseSearchServiceBlockingStub searchServiceBlockingStub;

    private final DictGrpcClient dictGrpcClient;
    /**
     * 主题映射器
     */
    private final WarningSubjectMapper warningSubjectMapper;

    /**
     * 搜索查询
     *
     * @param subjectWarningRequest 参数
     * @return {@link PageResponse}<{@link MessageContentVO}>
     */
    @Override
    public PageResponse<MessageContentVO> searchQuery(SubjectWarningRequest subjectWarningRequest) {
        WarningSubject subject = this.getById(subjectWarningRequest.getSubjectId());
        AssertUtils.isNotNull(subject, TopicExceptionEnum.TOPIC_NOT_EXISTS);
        // 查询未选择平台 使用配置的平台
        String subjectPlatform = StringUtils.isEmpty(subjectWarningRequest.getPlatform()) ? subject.getSubjectPlatform() : subjectWarningRequest.getPlatform();
        MessageRequest.MessageRequestBuilder messageRequestBuilder = MessageRequest.builder().searchKeywords(subject.getSubjectKeyword())
                .source(subjectPlatform).limit(subjectWarningRequest.getPageSize())
                // 按时间倒序排序
                .sort("-ps").accountId(subject.getSubjectAccount());
        if (Objects.nonNull(subjectWarningRequest.getEndTime())) {
            messageRequestBuilder.endDate(DateTimeFormatterUtil.localDateTimeFormatterToDateTime(subjectWarningRequest.getEndTime()));
        }
        if (Objects.nonNull(subjectWarningRequest.getStartTime())) {
            messageRequestBuilder.startDate(DateTimeFormatterUtil.localDateTimeFormatterToDateTime(subjectWarningRequest.getStartTime()));
        }
        if (!StringUtils.isEmpty(subject.getSubjectAccount())) {
            messageRequestBuilder.accountId(subject.getSubjectAccount());
        }
        Map<String, String> emotionMaps = dictGrpcClient.getDictMap("warning_message_emotion");
        messageRequestBuilder.sentiment(Strings.nullToEmpty(subjectWarningRequest.getEmotion()));
        messageRequestBuilder.tags(Strings.nullToEmpty(subjectWarningRequest.getLabel()));
        SearchRequest message = (SearchRequest) ProtoJsonUtil.toProtoMessage(SearchRequest.newBuilder(), JSON.toJSONString(messageRequestBuilder.build()));
        SearchPageResponse searchPageResponse = searchServiceBlockingStub.withMaxInboundMessageSize(Integer.MAX_VALUE).withMaxOutboundMessageSize(Integer.MAX_VALUE).baseSearch(message);
        Map<String, WarningLabelTree> warningLabelTreeMap = warningLabelTreeServiceImpl.allLabelValueMapping();
        List<MessageContentVO> messageContentVOList = searchPageResponse.getListList().stream()
                .map(searchResponseData -> this.objectConversion(searchResponseData, emotionMaps, warningLabelTreeMap))
                .collect(Collectors.toList());
        return PageResponse.builder(messageContentVOList, searchPageResponse.getTotal());
    }

    /**
     * 主题分析列表
     *
     * @param userId 用户id
     * @return {@link List}<{@link SubjectAnalysisVO}>
     */
    @Override
    public List<SubjectAnalysisVO> listSubjectAnalysis(Long userId) {
        List<WarningSubject> warningSubjects = warningSubjectMapper.listSubjectAnalysis(userId);
        Map<String, String> platformMap = dictGrpcClient.getDictMap("warning_message_source");
        return warningSubjects.stream().map(warningSubject -> SubjectAnalysisVO.build(warningSubject, platformMap)).collect(Collectors.toList());
    }

    /**
     * 添加主题
     *
     * @param addSubjectRequest 请求添加主题
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSubject(AddSubjectRequest addSubjectRequest) {
        WarningSubject warningSubject = JSON.parseObject(JSON.toJSONString(addSubjectRequest), WarningSubject.class);
        WarningSubject subject = this.judgingTopicRepetition(warningSubject.getSubjectName(), RequestHolderUtil.getUserId(), null);
        AssertUtils.isNull(subject, TopicExceptionEnum.TOPIC_NAME_ALREADY_EXISTS);
        int insertResult = warningSubjectMapper.insert(warningSubject);
        AssertUtils.isTrue(insertResult > 0, CommonEnum.FAIL);
        // 保存用户主题关系表
        warningSubjectAnalysisServiceImpl.addSubjectAnalysis(new WarningSubjectAnalysis(warningSubject.getId(), RequestHolderUtil.getUserId(), LocalDateTime.now()));
    }

    /**
     * 更新主题
     *
     * @param updateSubjectRequest 更新主题要求
     */
    @Override
    public void updateSubject(UpdateSubjectRequest updateSubjectRequest) {
        WarningSubject warningSubject = JSON.parseObject(JSON.toJSONString(updateSubjectRequest), WarningSubject.class);
        WarningSubject subject = this.judgingTopicRepetition(warningSubject.getSubjectName(), RequestHolderUtil.getUserId(), Collections.singletonList(updateSubjectRequest.getId()));
        AssertUtils.isNull(subject, TopicExceptionEnum.TOPIC_NAME_ALREADY_EXISTS);
        warningSubject.setSubjectUpdateTime(LocalDateTime.now());
        int updateResult = warningSubjectMapper.updateById(warningSubject);
        AssertUtils.isTrue(updateResult > 0, CommonEnum.FAIL);
    }

    /**
     * 删除主题
     *
     * @param id id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSubject(Long id) {
        WarningSubject warningSubject = this.getById(id);
        AssertUtils.isNotNull(warningSubject, TopicExceptionEnum.TOPIC_NOT_EXISTS);
        int deleteResult = warningSubjectMapper.deleteById(id);
        AssertUtils.isTrue(deleteResult > 0, CommonEnum.FAIL);
        warningSubjectAnalysisServiceImpl.deleteSubjectAnalysis(RequestHolderUtil.getUserId(), id);
    }

    /**
     * 得到主题
     *
     * @param id id
     * @return {@link WarningSubjectVO}
     */
    @Override
    public WarningSubjectVO getSubject(Long id) {
        WarningSubject warningSubject = warningSubjectMapper.selectById(id);
        AssertUtils.isNotNull(warningSubject, CommonEnum.QUERY_NOT_FOUND);
        return JSON.parseObject(JSON.toJSONString(warningSubject), WarningSubjectVO.class);
    }

    /**
     * 判断主题重复
     *
     * @param userId              用户id
     * @param subjectName         主题名称
     * @param exclusionSubjectIds 排除对象id
     * @return {@link WarningSubject}
     */
    @Override
    public WarningSubject judgingTopicRepetition(String subjectName, Long userId, List<Long> exclusionSubjectIds) {
        return warningSubjectMapper.judgingSubjectRepetition(subjectName, userId, exclusionSubjectIds);
    }

    /**
     * 通过id查询主题信息
     *
     * @param id id
     * @return {@link WarningSubject}
     */
    @Override
    public WarningSubject getById(Long id) {
        return warningSubjectMapper.selectById(id);
    }

}




